package data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import minigames.IMiniGame;

public class GameData
        implements IGameDataReadOnly
{
    private static final PlayerComparator PLAYER_COMPARATOR = new PlayerComparator();
    public final Object                   mPlayerListLock   = new Object();

    private GameState                     mGameState;
    private List<Player>                  mPlayers          = new ArrayList<>();
    private final List<IMiniGame>         mMiniGames        = new ArrayList<>();
    private IMiniGame                     mCurrentMiniGame  = null;

    public GameData()
    {
        reset();
    }

    public void reset()
    {
        mGameState = GameState.NOT_RUNNING;
        synchronized( mPlayerListLock )
        {
            mPlayers.clear();
        }
        mCurrentMiniGame = null;
    }

    @Override
    public List<IPlayerReadOnly> getReadOnlyPlayerList()
    {
        List<IPlayerReadOnly> playerReadOnlyList = new ArrayList<>();

        synchronized( mPlayerListLock )
        {
            playerReadOnlyList.addAll(mPlayers);
        }

        Collections.sort(playerReadOnlyList, PLAYER_COMPARATOR);

        return playerReadOnlyList;
    }

    public void addMiniGames( final List<IMiniGame> pMiniGames )
    {
        mMiniGames.addAll(pMiniGames);
    }

    public List<IMiniGame> getMiniGames()
    {
        return mMiniGames;
    }

    @Override
    public IMiniGame getCurrentMiniGame()
    {
        return mCurrentMiniGame;
    }

    public void setCurrentMiniGame( final IMiniGame pCurrentMiniGame )
    {
        mCurrentMiniGame = pCurrentMiniGame;
    }

    @Override
    public GameState getGameState()
    {
        return mGameState;
    }

    public void setGameState( final GameState pGameState )
    {
        mGameState = pGameState;
    }

    public void setPlayers( final List<Player> pPlayers )
    {
        synchronized( mPlayerListLock )
        {
            mPlayers.clear();
            mPlayers.addAll(pPlayers);
        }
    }

    public void addPlayer( final Player pPlayer )
    {
        synchronized( mPlayerListLock )
        {
            mPlayers.add(pPlayer);
        }
    }

    public List<Player> getPlayers()
    {
        return mPlayers;
    }

    public void resetReadynessOfHumanPlayers()
    {
        synchronized( mPlayerListLock )
        {
            for( Player currentPlayer : mPlayers )
            {
                if( currentPlayer.isAiPlayer() )
                {
                    continue;
                }
                currentPlayer.setReady(false);
            }
        }
    }

    public Player getPlayerForIp( final String mPlayerIp )
    {
        Player player = null;

        synchronized( mPlayerListLock )
        {
            for( Player currentPlayer : mPlayers )
            {
                if( currentPlayer.getIp().equals(mPlayerIp) )
                {
                    player = currentPlayer;
                    break;
                }
            }
        }
        return player;
    }

    public Player getPlayerForName( final String mPlayerName )
    {
        Player player = null;

        synchronized( mPlayerListLock )
        {
            for( Player currentPlayer : mPlayers )
            {
                if( currentPlayer.getName().equals(mPlayerName) )
                {
                    player = currentPlayer;
                    break;
                }
            }
        }
        return player;
    }

    public void removePlayer( final Player pPlayer )
    {
        synchronized( mPlayerListLock )
        {
            mPlayers.remove(pPlayer);
        }
    }

    public boolean removePlayerByNameIfAi( final String mName )
    {
        synchronized( mPlayerListLock )
        {
            Player removePlayer = null;
            for( Player currentPlayer : mPlayers )
            {
                if( currentPlayer.getName().equals(mName) )
                {
                    if( !currentPlayer.isAiPlayer() )
                    {
                        return false;
                    }

                    removePlayer = currentPlayer;
                    break;
                }
            }

            return mPlayers.remove(removePlayer);
        }
    }

    public int getNumberOfPlayers()
    {
        int nrOfPlayers = 0;
        synchronized( mPlayerListLock )
        {
            nrOfPlayers = mPlayers.size();
        }
        return nrOfPlayers;
    }

}
